package com.tsfyun.scm.service.impl.finance;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.draw.LineSeparator;
import com.tsfyun.common.base.dto.ExportFileDTO;
import com.tsfyun.common.base.enums.DistributedLockEnum;
import com.tsfyun.common.base.enums.RateTypeEnum;
import com.tsfyun.common.base.enums.domain.DomainOprationEnum;
import com.tsfyun.common.base.enums.domain.DomainTypeEnum;
import com.tsfyun.common.base.enums.domain.ImpSalesContractStatusEnum;
import com.tsfyun.common.base.enums.domain.PaymentAccountStatusEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.support.DomainStatus;
import com.tsfyun.common.base.util.*;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.validator.ValidatorUtils;
import com.tsfyun.scm.base.DataCalling;
import com.tsfyun.scm.dto.finance.ImpSalesContractQTO;
import com.tsfyun.scm.entity.customer.Customer;
import com.tsfyun.scm.entity.file.UploadFile;
import com.tsfyun.scm.entity.finance.ImpSalesContract;
import com.tsfyun.scm.entity.finance.ImpSalesContractMember;
import com.tsfyun.scm.entity.finance.Invoice;
import com.tsfyun.scm.entity.finance.InvoiceCostMember;
import com.tsfyun.scm.entity.order.ImpOrder;
import com.tsfyun.scm.entity.order.ImpOrderCost;
import com.tsfyun.scm.entity.order.ImpOrderMember;
import com.tsfyun.scm.mapper.finance.ImpSalesContractMapper;
import com.tsfyun.scm.service.customer.IImpClauseService;
import com.tsfyun.scm.service.file.IExportFileService;
import com.tsfyun.scm.service.file.IUploadFileService;
import com.tsfyun.scm.service.finance.*;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.service.order.IImpOrderMemberService;
import com.tsfyun.scm.service.order.IImpOrderService;
import com.tsfyun.scm.service.system.IExpenseSubjectService;
import com.tsfyun.scm.service.system.IStatusHistoryService;
import com.tsfyun.scm.service.system.ISubjectBankService;
import com.tsfyun.scm.service.system.ISubjectService;
import com.tsfyun.scm.vo.finance.*;
import com.tsfyun.scm.vo.order.ImpOrderCostVO;
import com.tsfyun.scm.vo.system.SubjectBankVO;
import com.tsfyun.scm.vo.system.SubjectVO;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.core.Local;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * <p>
 * 销售合同 服务实现类
 * </p>
 *

 * @since 2020-05-19
 */
@RefreshScope
@Slf4j
@Service
public class ImpSalesContractServiceImpl extends ServiceImpl<ImpSalesContract> implements IImpSalesContractService {

    @Autowired
    private ImpSalesContractMapper impSalesContractMapper;
    @Autowired
    private IInvoiceCostMemberService invoiceCostMemberService;
    @Autowired
    private IImpSalesContractMemberService impSalesContractMemberService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Autowired
    private IInvoiceService invoiceService;
    @Autowired
    private IImpOrderService impOrderService;
    @Autowired
    private IExportFileService exportFileService;
    @Autowired
    private IUploadFileService uploadFileService;
    @Value("${redis.lock.time:5}")
    private Integer lockTime;
    @Value("${file.directory}")
    private String filePath;
    @Autowired
    private IPaymentAccountService paymentAccountService;
    @Autowired
    private IImpOrderMemberService impOrderMemberService;
    @Autowired
    private ISubjectService subjectService;
    @Autowired
    private ISubjectBankService subjectBankService;
    @Autowired
    private IStatusHistoryService statusHistoryService;

    @Override
    public PageInfo<ImpSalesContractVO> pageList(ImpSalesContractQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto, Map.class);
        List<ImpSalesContractVO> list = impSalesContractMapper.list(params);
        return new PageInfo<>(list);
    }

    @Override
    public ImpSalesContractDetailPlusVO detail(Long id, String operation) {
        ImpSalesContractVO impSalesContract = impSalesContractMapper.selectById(id);
        Optional.ofNullable(impSalesContract).orElseThrow(()->new ServiceException("销售合同信息不存在"));
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.of(operation), impSalesContract.getStatusId());
        //获取销售合同明细信息
        List<ImpSalesContractMemberVO> members = impSalesContractMemberService.getMembersBySalesContractId(id);
        //获取费用明细信息
        List<InvoiceCostMemberVO> costMembers = invoiceCostMemberService.getMembersByOrderNo(impSalesContract.getImpOrderNo());
        return new ImpSalesContractDetailPlusVO(beanMapper.map(impSalesContract,ImpSalesContractVO.class),members,costMembers);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) {
        String lockKey = DistributedLockEnum.IMP_SALES_CONTRACT_DELETE.getCode() + ":"  + id;
        Lock lock = redisLockRegistry.obtain(lockKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(lockTime, TimeUnit.SECONDS);
            if (!isLock) {
                log.error(String.format("【%s】删除销售合同未获取到锁，销售合同id：【%s】", id));
                throw new ServiceException("服务拥挤，请稍后再试");
            }
            ImpSalesContract impSalesContract = super.getById(id);
            Optional.ofNullable(impSalesContract).orElseThrow(()->new ServiceException("销售合同信息不存在或者已经被删除"));
            Invoice invoice = invoiceService.getBySalesContractNo(impSalesContract.getDocNo());
            Optional.ofNullable(invoice).ifPresent(r->{
                throw new ServiceException(String.format("合同【%s】已经生成发票申请【%s】",impSalesContract.getDocNo(),invoice.getDocNo()));
            });
            //修改订单销售合同号为空
            impOrderService.updateSalesContractNo(impSalesContract.getImpOrderNo(),"");
            //删除合同费用明细
            invoiceCostMemberService.deleteByDocId(impSalesContract.getId().toString());
            //删除合同明细
            impSalesContractMemberService.deleteBySalesContractId(impSalesContract.getId());
            //删除合同主单
            super.removeById(id);
        } catch (InterruptedException e) {
            log.error(String.format("删除销售合同获取锁异，id：【%s】", id),e);
            throw new ServiceException("服务拥挤，请稍后再试");
        }finally {
            //释放锁
            lock.unlock();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setInvoiceNo(Long id, String salesContractNo, String invoiceNo) {
        impSalesContractMapper.updateInvoiceNo(id,salesContractNo,invoiceNo);
    }

    @Override
    public ImpSalesContractPlusVO getContractData(Long id) {
        ImpSalesContractVO impSalesContract = impSalesContractMapper.selectById(id);
        Optional.ofNullable(impSalesContract).orElseThrow(()->new ServiceException("销售合同信息不存在"));
        ImpOrder impOrder = impOrderService.findByDocNo(impSalesContract.getImpOrderNo());
        //获取销售合同明细信息
        List<ImpSalesContractMemberVO> members = impSalesContractMemberService.getMembersBySalesContractId(id);
        ImpSalesContractMainVO main = beanMapper.map(impSalesContract,ImpSalesContractMainVO.class);
        ValidatorUtils.isTrueCall(Objects.nonNull(impOrder),()->{
            main.setCustomerOrderNo(impOrder.getClientNo());
        });
        return new ImpSalesContractPlusVO(main,members);
    }

    @Override
    public Long contractPdf(Long id) {
        ImpSalesContractPlusVO impSalesContractPlusVO = getContractData(id);
        ExportFileDTO exportFileDTO =  generateContractPdf(impSalesContractPlusVO);
        Long fileId = exportFileService.save(exportFileDTO);
        return fileId;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void generateByImpOrder(ImpOrder impOrder, List<ImpOrderCostVO> orderCosts, Customer customer, BigDecimal adjustAmount) {
        // 排除费用 付汇手续费
//        List<String> excludeSubjects = Arrays.asList("A0006");
//        Iterator<ImpOrderCostVO> iterator = orderCosts.iterator();
//        while (iterator.hasNext()){
//            if(excludeSubjects.contains(iterator.next().getExpenseSubjectId())){
//                iterator.remove();
//            }
//        }
        //统计订单总关税金额、总消费税金额、总增值税金额、总货款、总其他费用
        BigDecimal tariffRateVal = StringUtils.rounded2(orderCosts.stream().filter(r->Objects.equals(r.getExpenseSubjectId(),"A0002")).map(ImpOrderCostVO::getReceAmount).reduce(BigDecimal.ZERO,BigDecimal::add)); //总关税
        BigDecimal exciseTaxVal = StringUtils.rounded2(orderCosts.stream().filter(r->Objects.equals(r.getExpenseSubjectId(),"A0004")).map(ImpOrderCostVO::getReceAmount).reduce(BigDecimal.ZERO,BigDecimal::add));//总消费税
        BigDecimal addedTaxTateVal = StringUtils.rounded2(orderCosts.stream().filter(r->Objects.equals(r.getExpenseSubjectId(),"A0003")).map(ImpOrderCostVO::getReceAmount).reduce(BigDecimal.ZERO,BigDecimal::add));//总增值税
        BigDecimal costGoodsVal = StringUtils.rounded2(orderCosts.stream().filter(r->Objects.equals(r.getExpenseSubjectId(),"A0005")).map(ImpOrderCostVO::getReceAmount).reduce(BigDecimal.ZERO,BigDecimal::add));//总货款
        BigDecimal otherVal = StringUtils.rounded2(orderCosts.stream().filter(r-> !Lists.newArrayList("A0002","A0003","A0004","A0005").contains(r.getExpenseSubjectId())).map(ImpOrderCostVO::getReceAmount).reduce(BigDecimal.ZERO,BigDecimal::add));//总其他费用
        log.info("订单【{}】，应收关税【{}】，应收消费税【{}】，应收增值税【{}】,应收货款【{}】，应收其他费用【{}】",impOrder.getDocNo(),tariffRateVal,exciseTaxVal,addedTaxTateVal,costGoodsVal,otherVal);
        List<InvoiceCostMember> invoiceCostMemberList = new ArrayList<>();
        //货款开票明细
        List<InvoiceCostMember> goodsCostMemberList = new ArrayList<>();
        orderCosts.stream().forEach(orderCost->{
            InvoiceCostMember invoiceCostMember = new InvoiceCostMember();
            invoiceCostMember.setExpenseSubjectId(orderCost.getExpenseSubjectId());
            //科目名称后面赋值
            invoiceCostMember.setExpenseSubjectName(orderCost.getExpenseSubjectName());
            invoiceCostMember.setCostMoney(orderCost.getReceAmount());
            if(Objects.equals(orderCost.getExpenseSubjectId(),"A0005")) { //货款
                invoiceCostMember.setMemo(orderCost.getMemo());
                goodsCostMemberList.add(invoiceCostMember);
            } else {
                invoiceCostMemberList.add(invoiceCostMember);
            }
        });
        //获取订单已完成的付汇单
        Map<String,Object> payedMap =  paymentAccountService.getPaymentAmount(impOrder.getId(), PaymentAccountStatusEnum.COMPLETED.getCode());
        BigDecimal payAccountValue = TypeUtils.castToBigDecimal(payedMap.get("accountValue"),BigDecimal.ZERO);//已付汇原币金额
        BigDecimal payAccountCnyValue = TypeUtils.castToBigDecimal(payedMap.get("accountValueCny"),BigDecimal.ZERO);//已付汇人民币金额
        log.info("客户【{}】订单【{}】已付汇原币金额【{}】，已付汇人民币金额【{}】",customer.getName(),impOrder.getDocNo(),payAccountValue,payAccountCnyValue);
        //超额付汇不能生成销售合同
        TsfPreconditions.checkArgument(payAccountValue.compareTo(impOrder.getTotalPrice()) <= 1,new ServiceException(String.format("订单【%s】存在超额付汇",impOrder.getDocNo())));
        BigDecimal goodsVal = BigDecimal.ZERO;//货款人民币金额
        if(payAccountValue.compareTo(impOrder.getTotalPrice()) == 0) { //付汇原币金额与订单金额一致
            log.info("订单【{}】付汇原币金额【{}】与订单金额【{}】一致",impOrder.getDocNo(),payAccountValue,impOrder.getTotalPrice());
            goodsVal = payAccountCnyValue;
            TsfPreconditions.checkArgument(payAccountCnyValue.compareTo(costGoodsVal) == 0,new ServiceException(String.format("订单【%s】货款应收与付汇人民币金额不一致",impOrder.getDocNo())));
            goodsCostMemberList.stream().forEach(invoiceCostMember->{
                invoiceCostMemberList.add(invoiceCostMember);
            });
        } else {
            log.info("订单【{}】付汇原币金额【{}】与订单金额【{}】不一致",impOrder.getDocNo(),payAccountValue,impOrder.getTotalPrice());

//            String rateTime = LocalDateTimeUtils.convertLocalAddHourMinuteStr(impOrder.getOrderDate(),"09:30");
//            RateTypeEnum rateType = RateTypeEnum.IMP_BANK_CHINA_SELL;
//            BigDecimal chinaRate = DataCalling.getInstance().obtainBankChinaRate(impOrder.getCurrencyId(), rateType.getCode(),rateTime);
//            TsfPreconditions.checkArgument(Objects.nonNull(chinaRate),new ServiceException(String.format("%s 外汇牌价卖出价暂未公布，请稍后重试",rateTime)));

            LocalDateTime nowTime = LocalDateTime.now();
            //获取海关汇率
            BigDecimal customsRate = DataCalling.getInstance().obtainCustomsRate(impOrder.getCurrencyId(),nowTime);
            TsfPreconditions.checkArgument(Objects.nonNull(customsRate),new ServiceException("未取到今日有效海关汇率请稍后重试"));

            InvoiceCostMember invoiceCostMember = new InvoiceCostMember();
            invoiceCostMember.setExpenseSubjectId("A0005");
            invoiceCostMember.setExpenseSubjectName("货款");
            goodsVal = impOrder.getTotalPrice().multiply(customsRate).setScale(2,BigDecimal.ROUND_HALF_UP);
            invoiceCostMember.setCostMoney(goodsVal);
            invoiceCostMember.setMemo(String.format("【%s】 未完成付汇；按当日海关汇率：【%s】；计算货款",LocalDateTimeUtils.formatTime(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss"),customsRate));
            invoiceCostMemberList.add(invoiceCostMember);
        }

        otherVal = StringUtils.rounded2(otherVal.add(goodsVal));
        //票差调整金额
        if(null != adjustAmount && adjustAmount.compareTo(BigDecimal.ZERO) != 0) {
            InvoiceCostMember adjustInvoiceCostMember = new InvoiceCostMember();
            adjustInvoiceCostMember.setExpenseSubjectId("A0016");
            adjustInvoiceCostMember.setExpenseSubjectName("票差调整金额");
            adjustInvoiceCostMember.setCostMoney(adjustAmount);
            invoiceCostMemberList.add(adjustInvoiceCostMember);
        }
        BigDecimal totalOtherVal = BigDecimal.ZERO;
        BigDecimal afterTariffRateVal = BigDecimal.ZERO;//计算后关税金额
        BigDecimal afterAddedTaxTateVal = BigDecimal.ZERO;//计算后增值税金额
        BigDecimal afterExciseTaxVal = BigDecimal.ZERO;//计算后消费税金额
        //根据订单明细生成销售合同明细
        List<ImpSalesContractMember> impSalesContractMemberList = new ArrayList<>();
        List<ImpOrderMember> orderMembers = impOrderMemberService.getByOrderId(impOrder.getId());
        for(ImpOrderMember orderMember : orderMembers) {
            //销售总价按总价摊 销售总价=（其他费用/订单总价）* 订单明细总价
            BigDecimal totalPrice = otherVal.divide(impOrder.getTotalPrice(), 2, BigDecimal.ROUND_HALF_UP).multiply(orderMember.getTotalPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
            totalOtherVal = totalOtherVal.add(totalPrice).setScale(2, BigDecimal.ROUND_HALF_UP);

            //关税
            totalPrice = totalPrice.add(orderMember.getTariffRateVal()).setScale(2, BigDecimal.ROUND_HALF_UP);
            afterTariffRateVal = afterTariffRateVal.add(orderMember.getTariffRateVal()).setScale(2, BigDecimal.ROUND_HALF_UP);
            //增值税
            totalPrice = totalPrice.add(orderMember.getAddedTaxTateVal()).setScale(2, BigDecimal.ROUND_HALF_UP);
            afterAddedTaxTateVal = afterAddedTaxTateVal.add(orderMember.getAddedTaxTateVal()).setScale(2, BigDecimal.ROUND_HALF_UP);
            //消费税
            totalPrice = totalPrice.add(orderMember.getExciseTaxVal()).setScale(2, BigDecimal.ROUND_HALF_UP);
            afterExciseTaxVal = afterExciseTaxVal.add(orderMember.getExciseTaxVal()).setScale(2, BigDecimal.ROUND_HALF_UP);

            ImpSalesContractMember impSalesContractMember = new ImpSalesContractMember();
            impSalesContractMember.setRowNo(orderMember.getRowNo());
            impSalesContractMember.setGoodsModel(orderMember.getModel());
            impSalesContractMember.setGoodsName(orderMember.getName());
            impSalesContractMember.setGoodsBrand(orderMember.getBrand());
            impSalesContractMember.setCountryId(orderMember.getCountry());
            impSalesContractMember.setCountryName(orderMember.getCountryName());
            impSalesContractMember.setQuantity(orderMember.getQuantity());
            impSalesContractMember.setUnitCode(orderMember.getUnitCode());
            impSalesContractMember.setUnitName(orderMember.getUnitName());
            impSalesContractMember.setTotalPrice(totalPrice);
            //根据数量计算单价（保留四位小数点）
            impSalesContractMember.setUnitPrice(impSalesContractMember.getTotalPrice().divide(impSalesContractMember.getQuantity(),4,BigDecimal.ROUND_HALF_UP));
            impSalesContractMember.setCurrencyId("CNY");
            impSalesContractMember.setCurrencyName("人民币");
            impSalesContractMemberList.add(impSalesContractMember);
        }

        //税金小于50不征收
        if(afterTariffRateVal.compareTo(BigDecimal.valueOf(50))==-1){afterTariffRateVal = BigDecimal.ZERO;}
        if(afterAddedTaxTateVal.compareTo(BigDecimal.valueOf(50))==-1){afterAddedTaxTateVal = BigDecimal.ZERO;}
        if(afterExciseTaxVal.compareTo(BigDecimal.valueOf(50))==-1){afterExciseTaxVal = BigDecimal.ZERO;}


        log.info("订单【{}】，应收关税【{}】，明细关税【{}】，应收增值税【{}】，明细增值税【{}】，应收消费税【{}】，明细消费税【{}】",impOrder.getDocNo(),tariffRateVal,
                afterTariffRateVal,addedTaxTateVal,afterAddedTaxTateVal,exciseTaxVal,afterExciseTaxVal);
        TsfPreconditions.checkArgument(tariffRateVal.compareTo(afterTariffRateVal) == 0,new ServiceException("订单关税金额与明细不一致"));
        TsfPreconditions.checkArgument(addedTaxTateVal.compareTo(afterAddedTaxTateVal) == 0,new ServiceException("订单增值税金额与明细不一致"));
        TsfPreconditions.checkArgument(exciseTaxVal.compareTo(afterExciseTaxVal) == 0,new ServiceException("订单消费税金额与明细不一致"));
        log.info("订单【{}】原其他费用金额【{}】，分摊后其他费用金额【{}】",impOrder.getDocNo(),otherVal,totalOtherVal);
        if(otherVal.compareTo(totalOtherVal) != 0) {
            log.info("订单【{}】需要调整票差，差额补至最后一条明细",impOrder.getDocNo());
            ImpSalesContractMember impSalesContractMember = impSalesContractMemberList.get(impSalesContractMemberList.size() - 1);
            impSalesContractMember.setTotalPrice(impSalesContractMember.getTotalPrice().subtract(totalOtherVal.subtract(otherVal).setScale(2,BigDecimal.ROUND_HALF_UP)).setScale(2,BigDecimal.ROUND_HALF_UP));
            impSalesContractMember.setUnitPrice(impSalesContractMember.getTotalPrice().divide(impSalesContractMember.getQuantity(),4,BigDecimal.ROUND_HALF_UP));
        }
        //创建销售合同和销售合同明细
        ImpSalesContract impSalesContract = new ImpSalesContract();
        impSalesContract.setDocNo(impOrder.getDocNo());
        //impSalesContract.setDocNo("S".concat(impOrder.getDocNo()));
        impSalesContract.setStatusId(ImpSalesContractStatusEnum.COMFIRMED.getCode());
        impSalesContract.setContractDate(impOrder.getOrderDate());
        impSalesContract.setImpOrderId(impOrder.getId());
        impSalesContract.setImpOrderNo(impOrder.getDocNo());
        impSalesContract.setBuyerId(customer.getId());
        impSalesContract.setBuyerName(customer.getName());
        impSalesContract.setBuyerBankName(customer.getInvoiceBankName());
        impSalesContract.setBuyerTaxpayerNo(customer.getTaxpayerNo());
        impSalesContract.setBuyerBankAccount(customer.getInvoiceBankAccount());
        impSalesContract.setBuyerBankAddress(customer.getInvoiceBankAddress());
        impSalesContract.setBuyerLinkPerson(customer.getLinkPerson());
        impSalesContract.setBuyerBankTel(customer.getInvoiceBankTel());
        //取企业信息和企业开票银行信息（默认的人民币）
        SubjectVO subject = subjectService.findByCode();
        List<SubjectBankVO> subjectBankVOS = subjectBankService.selectEnableBanks();
        TsfPreconditions.checkArgument(CollUtil.isNotEmpty(subjectBankVOS),new ServiceException("请联系管理员配置企业银行信息"));
        SubjectBankVO subjectBankVO = subjectBankVOS.stream().filter(r->Objects.equals("CNY",r.getCurrencyId())
                && Objects.equals(Boolean.TRUE,r.getIsDefault())).findFirst().orElseThrow(()->new ServiceException("请联系管理员配置默认的人民币企业银行信息"));
        impSalesContract.setSellerId(subject.getId());
        impSalesContract.setSellerBankName(subjectBankVO.getName());
        impSalesContract.setSellerBankAccount(subjectBankVO.getAccount());
        impSalesContract.setSellerBankAddress(subjectBankVO.getAddress());
        impSalesContract.setGoodsVal(goodsVal);
        impSalesContract.setDifferenceVal(adjustAmount);
        BigDecimal contractVal = impSalesContractMemberList.stream().map(ImpSalesContractMember::getTotalPrice).reduce(BigDecimal.ZERO,BigDecimal::add).setScale(2,BigDecimal.ROUND_HALF_UP);
        impSalesContract.setTotalPrice(contractVal);
        //保存销售合同及明细
        super.saveNonNull(impSalesContract);
        impSalesContractMemberService.saveMembers(impSalesContractMemberList,impSalesContract);
        //保存费用明细
        invoiceCostMemberService.saveMembers(invoiceCostMemberList,impSalesContract);
        //修改订单上的销售合同号
        impOrderService.updateSalesContractNo(impOrder.getDocNo(),impSalesContract.getDocNo());
        //记录单据状态变更
        statusHistoryService.saveHistory(DomainOprationEnum.SALES_CONTRACT_ORDER_APPLY,impSalesContract.getId().toString(), DomainTypeEnum.IMPSALESCONTRACT.getCode(),ImpSalesContractStatusEnum.COMFIRMED.getCode(),ImpSalesContractStatusEnum.COMFIRMED.getName());
    }


    @Override
    public ImpSalesContract getByOrderNo(String orderNo) {
        ImpSalesContract impSalesContract = new ImpSalesContract();
        impSalesContract.setImpOrderNo(orderNo);
        return super.getOne(impSalesContract);
    }

    @Override
    public ImpSalesContract findByOrderId(Long orderId) {
        ImpSalesContract impSalesContract = new ImpSalesContract();
        impSalesContract.setImpOrderId(orderId);
        return super.getOne(impSalesContract);
    }

    @Override
    public List<File> batchDownloadZip(List<Long> ids) {
        List<File> files = Lists.newArrayList();
        ids.stream().forEach(id->{
            ImpSalesContractPlusVO impSalesContractPlusVO = getContractData(id);
            ExportFileDTO exportFileDTO =  generateContractPdf(impSalesContractPlusVO);
            files.add(new File(exportFileDTO.getPath()));
        });
        return files;
    }

    public ExportFileDTO generateContractPdf(ImpSalesContractPlusVO impSalesContractPlusVO) {
        ImpSalesContractMainVO salesContract = impSalesContractPlusVO.getSalesContract();
        List<ImpSalesContractMemberVO> members = impSalesContractPlusVO.getMembers();
        //定义临时文件存放目录
        String path = filePath +"temp/"+ "scm" +"/salesContract/";
        String sysFileName = String.format("%s_%s.pdf",impSalesContractPlusVO.getSalesContract().getDocNo(), LocalDateTimeUtils.formatNow("yyyyMMddHHmmssSSS"));
        String fileName = String.format("%s_CONTRACT.pdf",salesContract.getDocNo());
        new File(path).mkdirs();
        Document document = null;
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(path.concat(File.separator + sysFileName));
            BaseFont bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",true);
            //标题的字体
            Font chFont = new Font(bfCN, 20, Font.NORMAL, BaseColor.BLACK);
            //正文的字体
            Font textFont = new Font(bfCN, 10, Font.NORMAL, BaseColor.BLACK);
            Rectangle rectangle = new Rectangle(PageSize.A4);
            document = new Document(rectangle);
            PdfWriter writer= PdfWriter.getInstance(document, out);
            document.open();
            //4.添加标题
            Paragraph content = new Paragraph("销售合同",chFont);
            content.setAlignment(Element.ALIGN_CENTER);
            document.add(content);
            content = new Paragraph("SALES CONTRACT",textFont);
            content.setAlignment(Element.ALIGN_CENTER);
            document.add(content);

            LineSeparator line = new LineSeparator(1, 100, new BaseColor(204, 204, 204), Element.ALIGN_CENTER, 0);
            Paragraph p_line = new Paragraph("",textFont);
            p_line.add(line);
            document.add(p_line);
            document.add(new Paragraph(" ",textFont));
            document.add(new Paragraph(" ",textFont));
            PdfPTable table = new PdfPTable(4);
            table.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
            table.setWidthPercentage(100);
            int[] array = {12, 38, 12, 38};
            table.setWidths(array);
            table.addCell(new Phrase("日期：",textFont));
            table.addCell(new Phrase(LocalDateTimeUtils.formatShort(salesContract.getContractDate()),textFont));
            table.addCell(new Phrase("合同编号：",textFont));
            table.addCell(new Phrase(StringUtils.null2EmptyWithTrim(salesContract.getDocNo()),textFont));
            table.addCell(new Paragraph("买方：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getBuyerName()),textFont));
            table.addCell(new Paragraph("卖方：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getSellerName()),textFont));
            table.addCell(new Paragraph("开户行：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getBuyerBankName()),textFont));
            table.addCell(new Paragraph("开户行：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getSellerBankName()),textFont));
            table.addCell(new Paragraph("银行账号：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getBuyerBankAccount()),textFont));
            table.addCell(new Paragraph("银行账号：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getSellerBankAccount()),textFont));
            table.addCell(new Paragraph("地址：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getBuyerBankAddress()),textFont));
            table.addCell(new Paragraph("地址：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getSellerBankAddress()),textFont));
            table.addCell(new Paragraph("电话：",textFont));
            table.addCell(new Paragraph(StringUtils.null2EmptyWithTrim(salesContract.getBuyerBankTel()),textFont));
            table.addCell(new Paragraph("",textFont));
            table.addCell(new Paragraph("",textFont));
            document.add(table);
            document.add(new Paragraph("兹经买卖双方同意由卖方出售买方购进如下货物，并按下列条款签定本合同：",textFont));
            document.add(new Paragraph("  ",textFont));

            table = new PdfPTable(2);
            table.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
            table.setWidthPercentage(100);
            int[] tableArray = {50, 50};
            table.setWidths(tableArray);
            table.addCell(new Paragraph("1.质量要求：由境外供应商提供，与卖方无关",textFont));
            table.addCell(new Paragraph("2.包装：原厂包装或供应商指定包装",textFont));
            table.addCell(new Paragraph("3.运输方式：运输方式由卖方负责，运输费用由买方承担",textFont));
            table.addCell(new Paragraph("4.付款条件：见《供应链服务框架协议》",textFont));
            table.addCell(new Paragraph("5.解决合同争议方式：向法院提出诉讼",textFont));
            table.addCell(new Paragraph("6.付款日期：见《供应链服务框架协议》",textFont));
            table.addCell(new Paragraph("7.合同一式两份，双方各执一份",textFont));
            table.addCell(new Paragraph("8.交货期限：见《供应链服务框架协议》",textFont));
            table.addCell(new Paragraph("9.产品名称、规格、数量、金额：",textFont));
            table.addCell(new Paragraph("",textFont));
            document.add(table);
            document.add(new Paragraph(" ",textFont));
            PdfPTable productsTable = new PdfPTable(9);
            productsTable.setWidthPercentage(100);
            int[] productsArray = {5,20,10,20,8,5,7,9,6};
            productsTable.setWidths(productsArray);
            productsTable.addCell(new Phrase("行号",textFont));
            productsTable.addCell(new Phrase("品名",textFont));
            productsTable.addCell(new Phrase("品牌",textFont));
            productsTable.addCell(new Phrase("型号",textFont));
            productsTable.addCell(new Phrase("数量",textFont));
            productsTable.addCell(new Phrase("单位",textFont));
            productsTable.addCell(new Phrase("单价",textFont));
            productsTable.addCell(new Phrase("总价",textFont));
            productsTable.addCell(new Phrase("币制",textFont));

            BigDecimal tquantity = members.stream().map(ImpSalesContractMemberVO::getQuantity).reduce(BigDecimal.ZERO,BigDecimal::add);
            BigDecimal ttotalPrice = members.stream().map(ImpSalesContractMemberVO::getTotalPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
            for(int i= 0,length = members.size();i < length;i++) {
                ImpSalesContractMemberVO member = members.get(i);
                productsTable.addCell(new Phrase(StringUtils.null2EmptyWithTrim(i + 1), textFont));
                productsTable.addCell(new Phrase(member.getGoodsName(), textFont));
                productsTable.addCell(new Phrase(member.getGoodsBrand(), textFont));
                productsTable.addCell(new Phrase(member.getGoodsModel(), textFont));
                PdfPCell cell = new PdfPCell(new Phrase(StringUtils.formatCurrency(member.getQuantity()), textFont));
                cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                productsTable.addCell(cell);
                productsTable.addCell(new Phrase(member.getUnitName(), textFont));
                cell = new PdfPCell(new Phrase(StringUtils.null2EmptyWithTrim(member.getUnitPrice()), textFont));
                cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                productsTable.addCell(cell);
                cell = new PdfPCell(new Phrase(StringUtils.formatCurrency(member.getTotalPrice()), textFont));
                cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                productsTable.addCell(cell);
                productsTable.addCell(new Phrase(member.getCurrencyName(), textFont));
            }
            PdfPCell cell = new PdfPCell(new Paragraph("合计：",textFont));
            cell.setColspan(4);
            productsTable.addCell(cell);
            cell = new PdfPCell(new Phrase(StringUtils.formatCurrency(tquantity),textFont));
            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
            productsTable.addCell(cell);
            productsTable.addCell(new Phrase(" ",textFont));
            productsTable.addCell(new Phrase(" ",textFont));
            cell = new PdfPCell(new Phrase(StringUtils.formatCurrency(ttotalPrice),textFont));
            cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
            productsTable.addCell(cell);
            document.add(productsTable);

            //图片签章处理
            if(StringUtils.isNotEmpty(salesContract.getSellerChapter())) {
                try{
                    UploadFile uploadFile = uploadFileService.getById(salesContract.getSellerChapter().replace("/scm/download/img/",""));
                    if(Objects.nonNull(uploadFile)){
                        Image image = Image.getInstance(uploadFile.getPath()+uploadFile.getNname());
                        image.scaleAbsolute(70,70);
                        image.setAlignment(Image.RIGHT|Image.UNDERLYING);
                        image.setAbsolutePosition(400,image.getAbsoluteY());
                        document.add(image);
                    }
                }catch (Exception e){}
            }

            PdfPTable autographTable = new PdfPTable(4);
            autographTable.setWidthPercentage(100);
            autographTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
            int[] autographArray = {20,30,20,30};
            autographTable.setWidths(autographArray);

            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));

            autographTable.addCell(new Phrase("买方r：",textFont));
            autographTable.addCell(new Phrase(salesContract.getBuyerName(),textFont));
            autographTable.addCell(new Phrase("卖方：",textFont));
            autographTable.addCell(new Phrase(salesContract.getSellerName(),textFont));

            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));

            autographTable.addCell(new Phrase("签字：",textFont));
            autographTable.addCell(new Phrase("",textFont));
            autographTable.addCell(new Phrase("签字：",textFont));
            autographTable.addCell(new Phrase("",textFont));

            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            autographTable.addCell(new Phrase(" ",textFont));
            document.add(autographTable);

            document.close();
            out.flush();
            out.close();

            ExportFileDTO exportFileDTO = new ExportFileDTO();
            exportFileDTO.setPath(path.concat(File.separator).concat(sysFileName));
            exportFileDTO.setFileName(fileName);
            exportFileDTO.setOnce(Boolean.TRUE);
            exportFileDTO.setOperator("系统自动生成");
            return exportFileDTO;
        } catch (Exception e) {
            log.error("生成销售合同PDF失败：",e);
            throw new ServiceException("生成合同PDF失败，请您稍后再试");
        } finally {
            if(document != null) {
                document.close();
            }
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {

                }
            }
        }
    }
}
